home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
program
/
svgakt50.zip
/
SRC
/
SVGAKIT
/
VBETEST.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-23
|
38KB
|
1,283 lines
/****************************************************************************
*
* VBETest - VESA VBE stress test program
*
* Copyright (C) 1994 SciTech Software.
* All rights reserved.
*
* Filename: $RCSfile: vbetest.c $
* Version: $Revision: 1.1 $
*
* Language: ANSI C
* Environment: IBM PC (MS DOS)
*
* Description: VBETest test program. This program is designed to stress
* test a VESA VBE implementation, and check it for full
* conformance with the VBE standard that it claims to conform
* to (supports only standards >= 1.2 standard).
*
* This program uses the SuperVGA test kit to perform all
* graphics output when testing the appropriate video modes
* for conformance (and thus only works on 386 and above
* machines).
*
* MUST be compiled in the large memory model.
*
* This program is freely distributable in the executable
* form. The source code is under the same restrictions as
* the SuperVGA kit it belong in.
*
* $Id: vbetest.c 1.1 1994/08/22 12:27:00 kjb release $
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <dos.h>
#include <string.h>
#include <conio.h>
#include <ctype.h>
#include "svga.h"
#include "getopt.h"
/*----------------------------- Implementation ----------------------------*/
/* Special UniVBE Information Block */
typedef struct {
char SuperVGAName[50]; /* Name of installed SuperVGA */
char DACName[50]; /* Name of installed DAC */
short SuperVGA; /* UniVBE SuperVGA id number */
short ChipID; /* UniVBE Chipset id number */
short Memory; /* Amount of memory installed */
short DacID; /* UniVBE DAC id number */
} UniVBEInfo;
/* SuperVGA information block */
typedef struct {
char VESASignature[4]; /* 'VESA' 4 byte signature */
short VESAVersion; /* VBE version number */
long OEMStringPtr; /* Far pointer to OEM string */
long Capabilities; /* Capabilities of video card */
long VideoModePtr; /* Far pointer to supported modes */
short TotalMemory; /* Number of 64kb memory blocks */
char reserved[232]; /* Pad to 256 byte block size */
UniVBEInfo far *univbeInfo; /* Special UniVBE information block */
} VgaInfoBlock;
/* SuperVGA mode information block */
typedef struct {
short ModeAttributes; /* Mode attributes */
char WinAAttributes; /* Window A attributes */
char WinBAttributes; /* Window B attributes */
short WinGranularity; /* Window granularity in k */
short WinSize; /* Window size in k */
short WinASegment; /* Window A segment */
short WinBSegment; /* Window B segment */
long WinFuncPtr; /* Far pointer to window function */
short BytesPerScanLine; /* Bytes per scanline */
short XResolution; /* Horizontal resolution */
short YResolution; /* Vertical resolution */
char XCharSize; /* Character cell width */
char YCharSize; /* Character cell height */
char NumberOfPlanes; /* Number of memory planes */
char BitsPerPixel; /* Bits per pixel */
char NumberOfBanks; /* Number of CGA style banks */
char MemoryModel; /* Memory model type */
char BankSize; /* Size of CGA style banks */
char NumberOfImagePages; /* Number of images pages */
char res1; /* Reserved */
char RedMaskSize; /* Size of direct color red mask */
char RedFieldPosition; /* Bit posn of lsb of red mask */
char GreenMaskSize; /* Size of direct color green mask */
char GreenFieldPosition; /* Bit posn of lsb of green mask */
char BlueMaskSize; /* Size of direct color blue mask */
char BlueFieldPosition; /* Bit posn of lsb of blue mask */
char RsvdMaskSize; /* Size of direct color res mask */
char RsvdFieldPosition; /* Bit posn of lsb of res mask */
char DirectColorModeInfo; /* Direct color mode attributes */
char res2[216]; /* Pad to 256 byte block size */
} ModeInfoBlock;
typedef struct {
int ax,bx,cx,dx,si,di,es,ds;
} regs;
FILE *logfile = NULL;
int CP_x,CP_y,VBEVersion,maxbanks,VBEFunc = 0,numErrors = 0,bits = 0;
int VBEMode = 0;
bool failed = false;
bool verbose = false;
bool doPageTest = false;
short modelist[100];
#include "version.c"
/* Table of memory model names */
char *memModelNames[] = {
"Text Mode",
"CGA Graphics",
"Hercules Graphics",
"4-plane planar",
"Packed Pixel",
"Non-chain 4, 256 color",
"Direct Color RGB",
"Direct Color YUV",
};
int queryCpu(void);
void out(const char *fmt, ... )
{
va_list argptr;
va_start(argptr, fmt);
vfprintf(stdout, fmt, argptr);
if (logfile)
vfprintf(logfile, fmt, argptr);
va_end(argptr);
}
void log(const char *fmt, ... )
{
va_list argptr;
va_start(argptr, fmt);
if (logfile) {
vfprintf(logfile, fmt, argptr);
fflush(logfile);
}
va_end(argptr);
}
/* Routine to convert the input value to its binary representation */
char *binary(unsigned value)
{
static char buf[11] = "00000000b";
unsigned mask = 0x80;
int i;
for (i = 0; i < 8; i++) {
buf[i] = value & mask ? '1' : '0';
mask >>= 1;
}
return buf;
}
bool checkEscape(void)
/****************************************************************************
*
* Function: checkEscape
* Returns: True if key was hit to advance to next test.
*
* Description: Checks if ESC has been hit, and exits if so.
*
****************************************************************************/
{
if (kbhit()) {
int ch = getch();
if (ch == 0) getch();
if (ch == 0x1B) {
restoreMode();
exit(1);
}
return true;
}
return false;
}
void startCheck(int _VBEFunc)
/****************************************************************************
*
* Function: startCheck
* Parameters: _VBEFunc - VBE Function number we are currently checking
*
* Description: Begins the logging of errors for this function.
*
****************************************************************************/
{
log("Checking function %02Xh ... ", VBEFunc = _VBEFunc);
numErrors = 0;
}
void endCheck(void)
/****************************************************************************
*
* Function: endCheck
*
* Description: Ends the checking of a particular VBE function.
*
****************************************************************************/
{
if (numErrors == 0)
log("Passed.\n");
else
log("\n%d errors logged for function %02Xh.\n", numErrors, VBEFunc);
}
void startModeCheck(int mode)
/****************************************************************************
*
* Function: startModeCheck
* Parameters: mode - VBE mode number being checked
*
* Description: Begins the logging of errors for this mode.
*
****************************************************************************/
{
log("Checking mode %02Xh ... ", VBEMode = mode);
if (verbose) log("\n");
numErrors = 0;
}
void endModeCheck(void)
/****************************************************************************
*
* Function: endModeCheck
*
* Description: Ends the checking of a particular VBE mode.
*
****************************************************************************/
{
if (numErrors == 0)
log("Passed.\n");
else
log("\n%d errors logged for mode %02Xh.\n", numErrors, VBEMode);
}
void fail(const char *msg, ... )
/****************************************************************************
*
* Function: fail
* Parameters: msg - Message describing error
*
* Description: Logs a failure message to the log file outlining the problem
* that was encountered.
*
****************************************************************************/
{
va_list argptr;
if (numErrors == 0)
log("\n\n");
numErrors++;
failed = true;
va_start(argptr, msg);
fprintf(logfile," ");
vfprintf(logfile, msg, argptr);
va_end(argptr);
}
bool callVBE(regs *r)
/****************************************************************************
*
* Function: callVBE
* Parameters: r - Structure holding register values to load
* Returns: True if successful, false if function failed
*
* Description: Loads the appropriate registers with the values from
* the register structure and executes and int 10h to call
* the VBE. It checks to ensure that register values are
* preserved across all calls correctly and ensures that the
* function executed successfully.
*
****************************************************************************/
{
union REGS rg;
struct SREGS sr;
int mask;
rg.x.ax = r->ax; rg.x.bx = r->bx;
rg.x.cx = r->cx; rg.x.dx = r->dx;
rg.x.si = r->si; rg.x.di = r->di;
sr.es = r->es; sr.ds = r->ds;
int86x(0x10,&rg,&rg,&sr);
if ((r->ax >> 8) != 0x4F) return TRUE;
/* Check to ensure all register are preserved across call. We define
* the mask to be a one for a register that must be preserved, and
* a zero for a register that can change. AX is always the result
* code, so this leave 7 bits to represent each register.
*/
switch (r->ax & 0xFF) {
case 0x00: mask = 0x7F; break;
case 0x01: mask = 0x7F; break;
case 0x02: mask = 0x7F; break;
case 0x03: mask = 0x7E; break;
case 0x04: if ((r->dx & 0xFF) == 0)
mask = 0x7E; /* State size call */
else mask = 0x7F; /* Other calls */
break;
case 0x05: if ((r->bx >> 8) == 0)
mask = 0x7F; /* Set window call */
else mask = 0x7B; /* Get window call */
break;
case 0x06: mask = 0x78; break;
case 0x07: if (r->bx == 0)
mask = 0x7F; /* Set display start */
else mask = 0x78; /* Get display start */
break;
case 0x08: mask = 0x7E; break;
default: mask = 0;
}
if ((mask & 0x01) && (r->bx != rg.x.bx))
fail("Function %02Xh failed to preserve BX\n", r->ax & 0xFF);
if ((mask & 0x02) && (r->cx != rg.x.cx))
fail("Function %02Xh failed to preserve CX\n", r->ax & 0xFF);
if ((mask & 0x04) && (r->dx != rg.x.dx))
fail("Function %02Xh failed to preserve DX\n", r->ax & 0xFF);
if (r->si != rg.x.si)
fail("Function %02Xh failed to preserve SI\n", r->ax & 0xFF);
if (r->di != rg.x.di)
fail("Function %02Xh failed to preserve DI\n", r->ax & 0xFF);
if (r->ds != sr.ds)
fail("Function %02Xh failed to preserve DS\n", r->ax & 0xFF);
if (r->es != sr.es)
fail("Function %02Xh failed to preserve ES\n", r->ax & 0xFF);
r->ax = rg.x.ax; r->bx = rg.x.bx;
r->cx = rg.x.cx; r->dx = rg.x.dx;
r->si = rg.x.si; r->di = rg.x.di;
r->es = sr.es; r->ds = sr.ds;
return (r->ax == 0x004F);
}
void checkFunction00h(void)
/****************************************************************************
*
* Function: checkFunction00h
*
* Description: Calls function 00h to determine if a VESA VBE is present,
* and check it for conformance.
*
****************************************************************************/
{
VgaInfoBlock vgaInfo;
regs r;
short i,*modes;
r.es = SEG(&vgaInfo);
r.di = OFF(&vgaInfo);
r.ax = 0x4F00;
if (callVBE(&r)) {
if (vgaInfo.VESAVersion < 0x102) {
out("Detected a VBE %d.%d interface. This program only checks interfaces that\n",
vgaInfo.VESAVersion >> 0x8,vgaInfo.VESAVersion & 0xF);
out("conform to the VBE 1.2 or later specifications.\n");
exit(1);
}
printf("VBE %d.%d Interface detected - checking for conformance\n\n",
vgaInfo.VESAVersion >> 0x8,vgaInfo.VESAVersion & 0xF);
log("VBE Version: %d.%d\n",vgaInfo.VESAVersion >> 0x8,
vgaInfo.VESAVersion & 0xF);
log("OEMString: %s\n",vgaInfo.OEMStringPtr);
log("Capabilities: %s (%04Xh)\n",binary(vgaInfo.Capabilities),
vgaInfo.Capabilities);
log("Total Memory: %d Kb\n",memory = vgaInfo.TotalMemory * 64);
if (verbose && vgaInfo.univbeInfo) {
log("\nUniVBE is installed. Current configuration:\n");
log(" %s\n", vgaInfo.univbeInfo->SuperVGAName);
log(" %s\n", vgaInfo.univbeInfo->DACName);
}
log("\nAvailable Modes:\n\n");
modes = (short*)vgaInfo.VideoModePtr;
i = 0;
while (*modes != -1) {
modelist[i] = *modes;
log("%04Xh ",*modes++);
if ((++i % 10) == 0)
log("\n");
}
modelist[i] = -1;
log("\n\n");
startCheck(0x00);
if (vgaInfo.TotalMemory == 0)
fail("TotalMemory field is zero!");
endCheck();
VBEVersion = vgaInfo.VESAVersion;
maxbanks = vgaInfo.TotalMemory;
}
else {
out("VESA VBE interface not detected.\n");
exit(1);
}
}
void checkFunction01h(void)
/****************************************************************************
*
* Function: checkFunction01h
*
* Description: Calls function 01h to obtain information about all
* available video modes, checking the values returned in the
* structure.
*
****************************************************************************/
{
ModeInfoBlock modeInfo;
regs r;
short *modes;
startCheck(0x01);
for (modes = modelist; *modes != -1; modes++) {
r.es = SEG(&modeInfo);
r.di = OFF(&modeInfo);
r.ax = 0x4F01;
r.cx = *modes;
if (callVBE(&r)) {
/* Ignore unsupported and text modes */
if ((modeInfo.ModeAttributes & 0x1) == 0)
continue;
if ((modeInfo.ModeAttributes & 0x10) == 0)
continue;
if (modeInfo.WinGranularity > 64 || modeInfo.WinGranularity == 0)
fail("Bad window granularity factor: %d\n",modeInfo.WinGranularity);
if (modeInfo.WinSize > 64 || modeInfo.WinSize == 0)
fail("Bad window size: %d\n",modeInfo.WinSize);
if ((modeInfo.WinAAttributes & 0x1) && modeInfo.WinASegment == 0)
fail("Bad window A segment value: %04Xh\n", modeInfo.WinASegment);
if ((modeInfo.WinBAttributes & 0x1) && modeInfo.WinBSegment == 0)
fail("Bad window B segment value: %04Xh\n", modeInfo.WinBSegment);
if (modeInfo.WinFuncPtr == NULL)
fail("NULL window function pointer\n");
}
else
fail("Video mode %03Xh not available yet listed in mode list\n", *modes);
}
endCheck();
}
void checkFunction02h(void)
/****************************************************************************
*
* Function: checkFunction02h
*
* Description: Calls function 02h to set each of the available video modes,
* draw a pattern and display status information about each
* video mode.
*
****************************************************************************/
{
ModeInfoBlock modeInfo;
regs r;
short *modes;
startCheck(0x02);
for (modes = modelist; *modes != -1; modes++) {
r.es = SEG(&modeInfo);
r.di = OFF(&modeInfo);
r.ax = 0x4F01;
r.cx = *modes;
if (callVBE(&r)) {
if ((modeInfo.ModeAttributes & 0x1) == 0)
continue;
r.ax = 0x4F02;
r.bx = *modes;
if (callVBE(&r)) {
r.ax = 0x4F03;
callVBE(&r);
if (r.bx != *modes)
fail("Function 03h did not return same video mode number (%04Xh instead of %04Xh)\n", r.bx, *modes);
}
}
}
r.ax = 0x3;
callVBE(&r);
endCheck();
}
void checkFunction04h(void)
/****************************************************************************
*
* Function: checkFunction04h
*
* Description: Calls function 04h to save and restore the SuperVGA
* video state.
*
****************************************************************************/
{
regs r;
int size;
void *savebuf;
startCheck(0x04);
r.ax = 0x4F04;
r.dx = 0x0000;
r.cx = 0x000F;
if (!callVBE(&r))
fail("Function 04h subfunction 00h failed.\n");
size = r.bx * 64;
if (size < 960)
fail("Invalid buffer size.\n");
if ((savebuf = malloc(size)) == NULL)
exit(1);
r.ax = 0x4F04;
r.dx = 0x0001;
r.cx = 0x000F;
r.es = SEG(savebuf);
r.bx = OFF(savebuf);
if (!callVBE(&r))
fail("Function 04h subfunction 01h failed.\n");
r.ax = 0x4F04;
r.dx = 0x0002;
r.cx = 0x000F;
r.es = SEG(savebuf);
r.bx = OFF(savebuf);
if (!callVBE(&r))
fail("Function 04h subfunction 02h failed.\n");
r.ax = 0x3;
callVBE(&r);
free(savebuf);
endCheck();
}
void checkFunction05h(void)
/****************************************************************************
*
* Function: checkFunction05h
*
* Description: Calls function 05h to change the video memory banks from
* the first bank all the way down to the last bank, and
* to read the bank values back again.
*
****************************************************************************/
{
ModeInfoBlock modeInfo;
regs r;
int bank;
bool twobanks;
startCheck(0x05);
r.es = SEG(&modeInfo);
r.di = OFF(&modeInfo);
r.ax = 0x4F01;
r.cx = 0x102;
callVBE(&r);
twobanks = modeInfo.WinBAttributes & 0x1;
r.ax = 0x4F02;
r.bx = 0x102;
if (!callVBE(&r))
fail("Could not set 800x600x16 color mode\n");
for (bank = 0; bank < maxbanks; bank++) {
r.ax = 0x4F05;
r.bx = 0x0000;
r.dx = bank;
if (!callVBE(&r))
fail("Bank switch routine failed.\n");
r.ax = 0x4F05;
r.bx = 0x0100;
if (!callVBE(&r))
fail("Bank switch routine failed.\n");
if (r.dx != bank)
fail("Differing bank 1 value returned (%04Xh instead of %04Xh)\n", r.dx, bank);
if (twobanks) {
r.ax = 0x4F05;
r.bx = 0x0001;
r.dx = bank;
if (!callVBE(&r))
fail("Bank switch routine failed.\n");
r.ax = 0x4F05;
r.bx = 0x0101;
if (!callVBE(&r))
fail("Bank switch routine failed.\n");
if (r.dx != bank)
fail("Differing bank 2 value returned (%04Xh instead of %04Xh)\n", r.dx, bank);
}
}
r.ax = 0x3;
callVBE(&r);
endCheck();
}
void clearAllPages(void)
/****************************************************************************
*
* Function: clearAllPages
*
* Description: Clears the entire video memory to black.
*
****************************************************************************/
{
int i;
char far *vmem = MK_FP(0xA000,0x0000);
for (i = 0; i < maxbanks; i++) {
setBank(i);
memset(vmem,0,0x7FFF);
memset(vmem+0x7FFF,0,0x7FFF);
}
}
void setDisplayStart(int x,int y)
/****************************************************************************
*
* Function: setDisplayStart
* Parameters: x,y - Position of the first pixel to display
*
* Description: Sets the new starting display position to implement
* hardware scrolling.
*
****************************************************************************/
{
regs r;
if (extendedflipping) {
r.ax = 0x4F07;
r.bx = 0x0000;
r.cx = x;
r.dx = y;
callVBE(&r);
r.ax = 0x4F07;
r.bx = 0x0001;
callVBE(&r);
if (abs(r.cx-x) > 8 || r.dx != y) {
fail("Invalid values returned by Function 07h subfunction 01h (cx = %04Xh, dx = %04Xh)\n", r.cx, r.dx);
fail("Should have been cx = %04Xh (can be rounded down), dx = %04Xh\n", x, y);
}
}
}
void setScanlineLength(int width,int *bytesperline,int *maxx,int *maxy)
/****************************************************************************
*
* Function: setScanlineLength
* Parameters: width - New scanline width to set in pixels
* bytesperline - New bytes per line value
* maxx - New maximum X coordinate
* maxy - New maximum Y coordinate
*
* Description: Attempts to set the logical scanline length using the
* VBE function 06h to set up a logical display buffer.
*
****************************************************************************/
{
regs r,r2;
r.ax = 0x4F06;
r.bx = 0x0000;
r.cx = width;
if (!callVBE(&r))
fail("Function 06h subfunction 00h failed.\n");
r2.ax = 0x4F06;
r2.bx = 0x0001;
if (!callVBE(&r2))
fail("Function 06h subfunction 01h failed.\n");
if (r.bx != r2.bx)
fail("Differing bytes per scanline values (%04Xh instead of %04Xh).\n",
r2.bx, r.bx);
if (r.cx != r2.cx)
fail("Differing pixels per scanline values (%04Xh instead of %04Xh).\n",
r2.cx, r.cx);
if (r.dx != r2.dx)
fail("Differing maximum scanline values (%04Xh instead of %04Xh).\n",
r2.dx, r.dx);
*bytesperline = r.bx;
*maxx = r.cx-1;
*maxy = r.dx-1;
}
void moire(void)
/****************************************************************************
*
* Function: moire
*
* Description: Draws a simple Moire pattern on the display screen using
* lines.
*
****************************************************************************/
{
int i,value;
clearAllPages();
if (maxcolor <= 255) {
for (i = 0; i < maxx; i += 10) {
line(maxx/2,maxy/2,i,0,i % maxcolor);
line(maxx/2,maxy/2,i,maxy,(i+1) % maxcolor);
}
for (i = 0; i < maxy; i += 10) {
line(maxx/2,maxy/2,0,i,(i+2) % maxcolor);
line(maxx/2,maxy/2,maxx,i,(i+3) % maxcolor);
}
}
else {
for (i = 0; i < maxx; i++) {
line(maxx/2,maxy/2,i,0,rgbColor(((i*255L)/maxx),0,0));
line(maxx/2,maxy/2,i,maxy,rgbColor(0,((i*255L)/maxx),0));
}
for (i = 0; i < maxy; i++) {
value = (i*255L)/maxy;
line(maxx/2,maxy/2,0,i,rgbColor(value,0,255 - value));
line(maxx/2,maxy/2,maxx,i,rgbColor(0,255 - value,value));
}
}
line(0,0,maxx,0,defcolor);
line(0,0,0,maxy,defcolor);
line(maxx,0,maxx,maxy,defcolor);
line(0,maxy,maxx,maxy,defcolor);
}
void gprintf(const char *fmt, ... )
/****************************************************************************
*
* Function: gprintf
* Parameters: fmt - Format string to display
*
* Description: Displays a string in the current display mode.
*
****************************************************************************/
{
va_list argptr;
char buf[255];
va_start(argptr, fmt);
vsprintf(buf,fmt,argptr);
writeText(CP_x,CP_y,buf,defcolor);
if (verbose) log(" %s\n", buf);
CP_y += 16;
va_end(argptr);
}
void dumpModeInfo(int mode,int displayAll)
/****************************************************************************
*
* Function: dumpModeInfo
* Parameters: mode - Mode number to dump info for
* displayAll - Should we display all mode info?
*
* Description: Dumps the information about the specific mode to the
* display.
*
****************************************************************************/
{
ModeInfoBlock modeInfo;
union REGS regs;
struct SREGS sregs;
sregs.es = FP_SEG(&modeInfo);
regs.x.di = FP_OFF(&modeInfo);
regs.x.ax = 0x4F01;
regs.x.cx = mode;
int86x(0x10,®s,®s,&sregs);
if ((modeInfo.ModeAttributes & 0x1) == 0)
return;
CP_x = CP_y = 5;
if (verbose)
log("\nMode information:\n");
gprintf("Mode number: %04Xh",mode);
if (displayAll) {
gprintf("ModeAttributes: %s (%04Xh)",binary(modeInfo.ModeAttributes),
modeInfo.ModeAttributes);
gprintf("WinAAttributes: %s (%04Xh)",binary(modeInfo.WinAAttributes),
modeInfo.WinAAttributes);
gprintf("WinBAttributes: %s (%04Xh)",binary(modeInfo.WinBAttributes),
modeInfo.WinBAttributes);
gprintf("WinGranulatiry: %d",modeInfo.WinGranularity);
gprintf("WinSize: %d",modeInfo.WinSize);
gprintf("WinASegment: %04Xh",modeInfo.WinASegment);
gprintf("WinBSegment: %04Xh",modeInfo.WinBSegment);
gprintf("WinFuncPtr: %04X:%04X",FP_SEG(modeInfo.WinFuncPtr),
FP_OFF(modeInfo.WinFuncPtr));
}
if (modeInfo.ModeAttributes & 0x10) {
gprintf("Resolution: %d x %d x %d bits per pixel (%02Xh BytesPerLine)",
modeInfo.XResolution,modeInfo.YResolution,modeInfo.BitsPerPixel,
modeInfo.BytesPerScanLine);
if (displayAll) {
gprintf("MemoryModel: %s",memModelNames[modeInfo.MemoryModel]);
gprintf("");
gprintf("CharSize: %d x %d",
modeInfo.XCharSize,modeInfo.YCharSize);
if (modeInfo.MemoryModel >= 6) {
gprintf("Red Component: %d bits, position %d",
modeInfo.RedMaskSize,modeInfo.RedFieldPosition);
gprintf("Green Component: %d bits, position %d",
modeInfo.GreenMaskSize,modeInfo.GreenFieldPosition);
gprintf("Blue Component: %d bits, position %d",
modeInfo.BlueMaskSize,modeInfo.BlueFieldPosition);
gprintf("Rsvd Component: %d bits, position %d",
modeInfo.RsvdMaskSize,modeInfo.RsvdFieldPosition);
gprintf("DirectColorInfo: %s (%d)",
binary(modeInfo.DirectColorModeInfo),
modeInfo.DirectColorModeInfo);
}
}
}
else {
gprintf("Resolution: %d x %d Text Mode (%d x %d charsize)",
modeInfo.XResolution,modeInfo.YResolution,
modeInfo.XCharSize,modeInfo.YCharSize);
}
gprintf("NumberOfPages: %d",modeInfo.NumberOfImagePages+1);
if (verbose)
log("\n");
}
void pageTest(int mode)
/****************************************************************************
*
* Function: pageTest
*
* Description: Interactive debugging of CRTC paging. We render an image to
* each of the available display pages, and then flip through
* the pages one by one, or to a specified display page
* depending on what the user specifies. We finish when the
* users hits the enter key (or quit on ESC).
*
****************************************************************************/
{
int i,ch,vpage,done = 0;
char buf[80];
/* Cycle through each of the display pages, printing the page number
* so that we can identify the page correctly.
*/
for (i = 0; i <= maxpage; i++) {
setActivePage(i);
moire();
dumpModeInfo(mode,false);
gprintf("");
gprintf("Page %d of %d", i+1, maxpage+1);
gprintf("u - Move up one page");
gprintf("d - Move down one page");
gprintf("U - Cycle up continuously (any key to stop)");
gprintf("D - Cycle down continuously (any key to stop)");
gprintf("1-9 - Display specified page");
line(0,0,maxx,0,defcolor);
line(0,0,0,maxy,defcolor);
line(maxx,0,maxx,maxy,defcolor);
line(0,maxy,maxx,maxy,defcolor);
}
vpage = 0;
while (!done) {
setVisualPage(vpage);
ch = getch();
if (ch == 0) getch();
switch (ch) {
case 'u':
if (++vpage > maxpage)
vpage = 0;
break;
case 'd':
if (--vpage < 0)
vpage = maxpage;
break;
case 'U':
while (!kbhit()) {
if (++vpage > maxpage)
vpage = 0;
setVisualPage(vpage);
}
getch();
break;
case 'D':
while (!kbhit()) {
if (--vpage < 0)
vpage = maxpage;
setVisualPage(vpage);
}
getch();
break;
case 0xD:
done = 1;
break;
case 0x1B:
restoreMode();
exit(1);
default:
ch -= '1';
if (ch >= 0 && ch <= maxpage)
vpage = ch;
break;
}
}
setActivePage(0);
}
void scrollTest(void)
/****************************************************************************
*
* Function: scrollTest
*
* Description: Checks the CRT display start routines to scroll the display
* page up and then back down again.
*
****************************************************************************/
{
int i,max;
if (extendedflipping) {
if (maxcolor == 15)
max = (memory*256L) / bytesperline - maxy;
else
max = (memory*1024L) / bytesperline - maxy;
if (max > maxy) max = maxy+1;
if (max < 0) return;
setDisplayStart(0,0);
for (i = 0; i < max; i++) { /* Scroll the display up */
setDisplayStart(0,i);
if (checkEscape())
return;
}
if (checkEscape())
return;
for (i--; i >= 0; i--) { /* Scroll the display down */
setDisplayStart(0,i);
if (checkEscape())
return;
}
}
}
void virtualTest(void)
/****************************************************************************
*
* Function: virtualTest
*
* Description: Checks the CRT logical scanline length routines, setting
* up a virtual display buffer and scrolling around within
* this buffer.
*
****************************************************************************/
{
int i,x,y,scrollx,scrolly,oldmaxx,oldmaxy,max;
char buf[80];
if (extendedflipping) {
/* Find the largest value that we can set the virtual buffer width
* to that the VBE supports
*/
switch (maxcolor) {
case 0xF: max = (memory*2048L) / (maxy+1); break;
case 0xFF: max = (memory*1024L) / (maxy+1); break;
case 0x7FFF:
case 0xFFFF: max = (memory*512L) / (maxy+1); break;
case 0xFFFFFF: max = (memory*341L) / (maxy+1); break;
}
oldmaxx = maxx;
oldmaxy = maxy;
for (i = max; i > oldmaxx+1; i--) {
setScanlineLength(i,&bytesperline,&maxx,&maxy);
if (maxx > oldmaxx+1 && maxx < max)
break; /* Large value has been set */
}
/* Perform huge horizontal scroll */
setDisplayStart(0,0);
clearAllPages();
moire();
writeText(20,20,"Function 06h - Set/Get Logical Scan Line Length",defcolor);
if (maxx == oldmaxx)
sprintf(buf,"Virtual buffer could not be resized (still %d x %d pixels)",maxx+1,maxy+1);
else
sprintf(buf,"Virtual buffer now set to %d x %d pixels",maxx+1,maxy+1);
writeText(20,40,buf,defcolor);
if (verbose) log(" %s\n", buf);
scrollx = maxx-oldmaxx;
scrolly = maxy-oldmaxy;
for (x = y = 0; x <= scrollx; x++) {
setDisplayStart(x,y);
if (checkEscape())
return;
}
for (x = scrollx,y = 0; y <= scrolly; y++) {
setDisplayStart(x,y);
if (checkEscape())
return;
}
for (x = scrollx,y = scrolly; x >= 0; x--) {
setDisplayStart(x,y);
if (checkEscape())
return;
}
for (x = 0,y = scrolly; y >= 0; y--) {
setDisplayStart(x,y);
if (checkEscape())
return;
}
if (maxx == oldmaxx) return;
/* Now perform huge vertical scroll */
delay(750);
setScanlineLength(oldmaxx,&bytesperline,&maxx,&maxy);
clearAllPages();
moire();
writeText(20,20,"Function 06h - Set/Get Logical Scan Line Length",defcolor);
sprintf(buf,"Virtual buffer now set to %d x %d pixels",maxx+1,maxy+1);
writeText(20,40,buf,defcolor);
if (verbose) log(" %s\n",buf);
scrolly = maxy-oldmaxy;
for (y = 0; y <= scrolly; y++) {
setDisplayStart(0,y);
if (checkEscape())
return;
}
for (y = scrolly; y >= 0; y--) {
setDisplayStart(0,y);
if (checkEscape())
return;
}
}
}
void wideDACTest(void)
/****************************************************************************
*
* Function: wideDACTest
*
* Description: Displays a set of color values using the wide DAC support
* if available.
*
****************************************************************************/
{
int i,bits,x,y;
palette pal[256];
palette oldpal[256];
regs r;
getPalette(0, 256, oldpal);
/* Set the DAC into the 8 bit mode if possible */
r.ax = 0x4F08; /* Set DAC service */
r.bx = 0x0800; /* BH := 8, BL := 0 (set DAC width) */
if (!callVBE(&r))
bits = 6;
else bits = r.bx >> 8;
if (bits != 6 && bits != 8)
fail("Function 08h subfunction 0h returned incorrect value (bh = %d)\n", bits);
r.ax = 0x4F08;
r.bx = 0x0001; /* Get DAC width (should now be 8) */
if (!callVBE(&r))
fail("Function 08h subfunction 01h failed.\n");
if ((r.bx >> 8) != bits)
fail("Functions 08h subfunction 01h returned incorrect value (%d instead of %d)\n", r.bx >> 8, bits);
memset(pal,0,256*3);
for (i = 0; i < 256; i += 4) {
pal[64 + (i >> 2)].red = i;
pal[128 + (i >> 2)].green = i;
pal[192 + (i >> 2)].blue = i;
}
pal[defcolor].red = 255;
pal[defcolor].green = 255;
pal[defcolor].blue = 255;
setPalette(0,256,pal);
clear(0);
line(0,0,maxx,0,defcolor);
line(0,0,0,maxy,defcolor);
line(maxx,0,maxx,maxy,defcolor);
line(0,maxy,maxx,maxy,defcolor);
x = y = 20;
writeText(x,y,"Function 08h - Set/Get DAC width",defcolor);
y += 32;
if (bits == 8) {
if (verbose) log(" 8 bit wide DAC supported\n");
writeText(x,y,"You should see a smooth transition of colors",defcolor);
y += 16;
writeText(x,y,"If the colors are broken into 4 lots, the wide DAC is not working",defcolor);
y += 32;
for (i = 0; i < 192; i++) {
line(x+i, y, x+i, y+32, 64+i/3);
line(x+i, y+32, x+i, y+64, 128+i/3);
line(x+i, y+64, x+i, y+96, 192+i/3);
}
}
else {
writeText(x,y,"BIOS does not support 8 bit wide DAC.",defcolor);
if (verbose) log(" 8 bit wide DAC NOT supported\n");
}
delay(750);
if (!set6BitPalette())
fail("Could not return to 6 bit DAC mode.\n");
setPalette(0, 256, oldpal);
}
void checkGraphicsFunctions(void)
/****************************************************************************
*
* Function: checkGraphicsFunctions
*
* Description: Intialises all of the available video modes, and performs
* testing on all the modes. We call upon the SuperVGA
* test kit to perform the graphics output for us for each
* video mode.
*
****************************************************************************/
{
ModeInfoBlock modeInfo;
regs r;
short *modes;
initSuperVGA(true);
for (modes = modelist; *modes != -1; modes++) {
r.es = SEG(&modeInfo);
r.di = OFF(&modeInfo);
r.ax = 0x4F01;
r.cx = *modes;
if (bits >= 0x100 && *modes != bits)
continue;
if (callVBE(&r)) {
if ((modeInfo.ModeAttributes & 0x1) == 0)
continue;
if (modeInfo.MemoryModel < 3)
continue;
if (bits != 0 && bits < 0x100 && modeInfo.BitsPerPixel != bits)
continue;
startModeCheck(*modes);
setSuperVGAMode(*modes);
checkEscape();
if (doPageTest)
pageTest(*modes);
else {
moire();
dumpModeInfo(*modes,true);
scrollTest();
checkEscape();
delay(750);
}
if (maxcolor == 255)
wideDACTest();
checkEscape();
if (!doPageTest)
virtualTest();
delay(750);
restoreMode();
endModeCheck();
}
checkEscape();
}
}
void banner(void)
{
out("VBETest - VESA VBE stress test program (Version %s)\n", version);
out(" Copyright (C) 1994 SciTech Software\n\n");
}
void help(void)
{
banner();
printf("Usage: vbetest [-vph] [-b<bits>] [-m<mode>]\n\n");
printf("By specifying the number of 'bits' to test, you can restrict VBETest to\n");
printf("run the time consuming graphical test only for the modes with the specified\n");
printf("number of bits per pixel. Likewise you can specify a single 'mode' (in hex).\n\n");
printf("For example:\n");
printf(" vbetest -b8 - Test all 8 bits per pixel (256 color) video modes\n");
printf(" vbetest -m101 - Test only mode 101h (640x480x256)\n\n");
printf("Options are:\n");
printf(" -v - Dump verbose debugging information to the VBETEST.LOG file\n");
printf(" -p - Interactive CRTC paging (otherwise uses CRTC scrolling)\n");
printf(" -b<x> - Only test modes with 'x' bits per pixel\n");
printf(" -m<x> - Only test mode with internal mode number 'x'\n");
printf(" -h - Display this help information\n");
exit(1);
}
void main(int argc, char *argv[])
{
int option;
char *argument;
if (queryCpu() < 4) {
printf("This program contains '386 specific instructions, and will not work on\n");
printf("this machine - sorry\n");
}
do {
option = getopt(argc,argv,"vVpPhHb:B:m:M:",&argument);
if (isascii(option))
option = tolower(option);
switch(option) {
case 'v':
verbose = true;
break;
case 'p':
doPageTest = true;
break;
case 'b':
bits = atoi(argument);
break;
case 'm':
sscanf(argument, "%x", &bits);
break;
case 'h':
case PARAMETER:
case INVALID:
help();
}
} while (option != ALLDONE);
if ((logfile = fopen("vbetest.log","wt")) == NULL) {
out("Unable to open log file!!\n");
exit(1);
}
banner();
printf("This program will test every function in the VESA VBE interface specifications\n");
printf("for correct conformance. If any errors are encountered, they will be logged to\n");
printf("the file 'vbetest.log' in the current directory.\n\n");
printf("Hit any key to start, or ESC anytime to cancel.\n");
if (getch() == 0x1B)
exit(1);
checkFunction00h();
checkFunction01h();
checkFunction02h();
checkFunction04h();
checkFunction05h();
checkGraphicsFunctions();
log("\n");
if (failed)
out("Video BIOS failed conformance test. Check log report for details.\n");
else if (!extendedflipping) {
out("Video BIOS passed most tests, but does not implement extended CRT\n");
out("addressing, used by some newer programs (like Microsoft Flight\n");
out("simulator\n");
}
else
out("Congratulations! Video BIOS passed all conformance tests.\n");
}